package com.itdct.onflow.core.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.itdct.onflow.core.mp.ContextPaginationInnerInterceptor;
import com.itdct.onflow.core.mp.DeleteMpInterceptor;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;

import jakarta.annotation.Resource;

/**
 * @author DCT
 * @version 1.0
 * @date 2023/6/8 18:08:25
 * @description
 */
@Configuration
@ConditionalOnProperty(prefix = "mybatis-plus", name = "mapper-locations")
@MapperScan(
        basePackages = "${onflow.project-package-name:com.itdct.onflow}" + ".**.mapper",
        sqlSessionFactoryRef = "mybatisPrimarySqlSessionFactory"
)
public class MybatisConfig {
    @Resource
    private DataSource dataSource;
    @Value("${mybatis-plus.mapper-locations:#{NULL}}")
    private String mapperLocations;
    @Value("${mybatis.type-aliases-package:#{NULL}}")
    private String typeAliasesPackage;
    @Value("${mybatis-plus.global-config.db-config.logic-delete-field:del}")
    private String deleteFieldName;
    @Autowired
    private OnflowConfig onflowConfig;

    /**
     * 注册事务管理器
     *
     * @return
     */
    @Primary
    @Bean("mybatisPrimaryPlatformTransactionManager")
    public PlatformTransactionManager platformTransactionManager() {
        return new DataSourceTransactionManager(dataSource);
    }

    @ConfigurationProperties(prefix = "mybatis.configuration")
    @Bean
    public org.apache.ibatis.session.Configuration globalConfiguration() {
        return new org.apache.ibatis.session.Configuration();
    }

    /**
     * 配置SqlSession工厂
     *
     * @return
     * @throws Exception
     */
    @Bean("mybatisPrimarySqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(
            GlobalConfig globalConfig,
            MybatisPlusInterceptor mybatisPlusInterceptor,
            org.apache.ibatis.session.Configuration globalConfiguration)
            throws Exception {
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        //指定数据源
        factoryBean.setDataSource(dataSource);
        MybatisConfiguration configuration = new MybatisConfiguration();
        BeanUtils.copyProperties(globalConfiguration, configuration);
        // 默认开启驼峰命名
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.addInterceptor(mybatisPlusInterceptor);

        //configuration.setLogImpl(StdOutImpl.class);
        factoryBean.setConfiguration(configuration);
        // 将mapper 的 xml文件路径交给sqlSessionFactory，否则自定义xml不会生效。
        //指定所有mapper.xml所在路径
        if (!StringUtils.isEmpty(mapperLocations)) {
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            factoryBean.setMapperLocations(resolver.getResources(mapperLocations));
        }
        // 配置是否支持 resultType的使用方式
        if (!StringUtils.isEmpty(typeAliasesPackage)) {
            factoryBean.setTypeAliasesPackage(typeAliasesPackage);
        }
        globalConfig.setEnableSqlRunner(true);

        GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
        dbConfig.setLogicDeleteField(onflowConfig.getLogicDelete().getLogicDeleteField());
        dbConfig.setLogicNotDeleteValue("0");
        dbConfig.setInsertStrategy(FieldStrategy.DEFAULT);
        dbConfig.setUpdateStrategy(FieldStrategy.ALWAYS);
        factoryBean.setGlobalConfig(globalConfig);
//        factoryBean.setDatabaseIdProvider(databaseIdProvider);
        return factoryBean.getObject();
    }

    // 最新版
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new DeleteMpInterceptor(deleteFieldName));
//        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        interceptor.addInnerInterceptor(new ContextPaginationInnerInterceptor(DbType.MYSQL));
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

        return interceptor;
    }

    @Bean
    public GlobalConfig globalConfig() {
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setEnableSqlRunner(true);
        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
        globalConfig.setDbConfig(dbConfig);
        dbConfig.setUpdateStrategy(FieldStrategy.ALWAYS);
        dbConfig.setLogicDeleteField(onflowConfig.getLogicDelete().getLogicDeleteField());
        dbConfig.setLogicNotDeleteValue("0");
        return globalConfig;
    }

}
